﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Physis.Security {

    public class RoleMembership : Core.CoreObject {
        
        #region Private Properties

        private Int64 roleId = 0;

        private Int64 userAccountId = 0;


        private UserAccount userAccount = null;

        private Role role = null;
        
        #endregion 


        #region Public Properties

        public Int64 RoleId { get { return roleId; } set { roleId = value; } }

        public Int64 UserAccountId { get { return userAccountId; } set { userAccountId = value; } }


        [System.Web.Script.Serialization.ScriptIgnore]
        [Newtonsoft.Json.JsonIgnore]
        public Role Role {

            get {

                if (role == null) { role = Application.Security.Role (RoleId, true); }

                return role;

            }

            set { role = value; } // ALLOW THIS TO BE SET BY A PARENT/OWNER OBJECT 

        }

        public String RoleName { get { return ((Role != null) ? Role.Name : String.Empty); } }

        public String EnvironmentName { get { return ((Role != null) ? Role.EnvironmentName : String.Empty); } }


        [System.Web.Script.Serialization.ScriptIgnore]
        [Newtonsoft.Json.JsonIgnore]
        public UserAccount UserAccount {

            get {

                if (userAccount == null) { userAccount = Application.Security.UserAccount (userAccountId, true); }

                return userAccount;

            }
        
        }

        public String SecurityAuthorityName { get { return ((UserAccount != null) ? UserAccount.SecurityAuthorityName : String.Empty); } }

        public String UserAccountName { get { return ((UserAccount != null) ? UserAccount.Name : String.Empty); } }

        #endregion 

        
        #region Constructors

        public RoleMembership () { /* DO NOTHING, FOR JSON DESERIALIZATION ONLY */ }

        public RoleMembership (Application forApplication) : base (forApplication) {

            return;

        }

        public RoleMembership (Application forApplication, Int64 forId) : base (forApplication) {

            if (!Load (forId, Application.EnterpriseDatabase)) {

                throw new Exception (GetType ().FullName + ".Load [Failed]: " + forId);

            }

            return;

        }

        #endregion


        #region Database Functions 
        
        protected override Dictionary<string, string> Validate () {

            // VALIDATE THAT THE ROLE AND PERMISSION ARE GOOD, SINCE THE OWNING ROLE COULD BE BRAND NEW AND IN A TRANSACTION, WE NEED TO JUST CHECK LOCAL 

            // DO NOT CALL THE BASE VALIDATIONS SINCE NAME/DESCRIPTION ARE NOT REQUIRED 

            Dictionary<String, String> validationErrors = new Dictionary<String, String> ();

            if (roleId == 0) { validationErrors.Add ("Role", "Role Reference is empty or null."); }

            if (userAccountId == 0) { validationErrors.Add ("User Account", "User Account Reference is empty or null."); }

            return validationErrors;

        }

        public override void MapDataFields (System.Data.DataRow currentRow) {

            base.MapDataFields (currentRow);

            roleId = Data.Readers.DataReader.Int64FromDatabase (currentRow, "RoleId");

            userAccountId = Data.Readers.DataReader.Int64FromDatabase (currentRow, "UserAccountId");

            return;

        }

        public override Boolean Save () {

            Boolean success = false;

            try {

                Dictionary<String, String> validationErrors = Validate ();

                if (validationErrors.Count > 0) {

                    Application.SetLastException (new Exception ("Invalid [" + validationErrors.Keys.First () + "]: " + validationErrors.Values.First ()));

                    return false;

                }

                UpdateModifiedToSessionUser ();


                System.Data.IDbCommand command = Application.EnterpriseDatabase.CreateCommand (ObjectType + "_InsertUpdate");

                command.CommandType = System.Data.CommandType.StoredProcedure;


                Application.EnterpriseDatabase.AppendCommandParameter (command, "RoleId", RoleId);

                Application.EnterpriseDatabase.AppendCommandParameter (command, "UserAccountId", UserAccountId);

                Application.EnterpriseDatabase.AppendCommandParameter (command, "ModifiedId", Application.Session.UserAccountName, 60);

                success = (command.ExecuteNonQuery () > 0);

                if (success) { SetIdentity (Application.EnterpriseDatabase); }

            }

            catch (Exception exception) {

                success = false;

                Application.SetLastException (exception);

            }

            return success;

        }

        #endregion 


    }

}
